package com.laomou.poker.rule.bull;

import java.util.ArrayList;
import java.util.List;

import com.java.rapid.Action;
import com.java.rapid.Condition;
import com.java.rapid.Condition3;
import com.java.rapid.Return;
import com.java.rapid.list.raList;
import com.java.rapid.list.raListGroup;
import com.laomou.poker.Poker;
import com.laomou.poker.PokerGroup;
import com.laomou.poker.PokerNum;
import com.laomou.poker.rule.AbsPokerRule;
import com.laomou.poker.rule.PokerRuleType;

public class Bull extends AbsPokerRule {

    @Override
    public PokerRuleType getRuleType() {
        return PokerRuleType.斗牛;
    }

    @Override
    public int getPlayerPokerCount() {
        return 5;
    }

    @Override
    public int getPokerCount() {
        return 1;
    }

    @Override
    public boolean isRule(final PokerGroup pokerGroup) {
        if (pokerGroup.size() != 5) {
            return false;
        }
        if (hasSame(pokerGroup, 4)) {
            pokerGroup.setType(BullType.炸弹);
            return true;
        }
        if (hasSameColor(pokerGroup, 5)) {
            pokerGroup.setType(BullType.五花);
            return true;
        }
        if (hasSameColor(pokerGroup, 4)) {
            pokerGroup.setType(BullType.四花);
            return true;
        }
        ArrayList<Poker> clist = new ArrayList<Poker>(pokerGroup.get());
        List<Poker> list = raList.from(clist).filter(new Condition<Poker>() {

            @Override
            public boolean apply(Poker input) {
                if (input.value() == PokerNum.方块A.value()) {
                    return false;
                }
                if (input.value() > PokerNum.方块5.value()) {
                    return true;
                }
                return false;
            }
        }).toList();
        int count = raList.from(clist).count(new Return<Poker, Integer>() {

            @Override
            public Integer result(Poker poker) {
                int ret = poker.value();
                if (poker.value() == PokerNum.方块A.value()) {
                    ret = 1;
                }
                return ret;
            }
        });
        // 5张牌都小于5,并且全部加起来小于10
        if (list.size() == 5 && count < 10) {
            pokerGroup.setType(BullType.五小);
            return true;
        }

        raListGroup.from1(pokerGroup.get()).select(3)
                .filter(new Condition3<Poker>() {

                    @Override
                    public boolean apply(List<Poker> t) {
                        return (value(t.get(0)) + value(t.get(1)) + value(t
                                .get(2))) % 10 == 0;
                    }
                }).not().forEach(new Action<List<Poker>>() {

            @Override
            public void call(List<Poker> output) {
                int ret = 0;
                for (Poker p : output) {
                    ret += value(p);
                }
                int bull = ret % 10;
                if (pokerGroup.type() == null) {
                    setBull(pokerGroup, ret);
                } else {
                    if (bull > pokerGroup.type().value()) {
                        setBull(pokerGroup, ret);
                    }
                }
            }
        });
        return true;
    }

    @Override
    public boolean isGreater(PokerGroup lp, PokerGroup rp) {
        if (lp.type() == null) {
            return false;
        }
        if (rp.type() == null) {
            return true;
        }
        return lp.type().value() > rp.type().value();
    }

    private int value(Poker p) {
        int ret = p.value();
        if (p.value() == PokerNum.方块J.value()
                || p.value() == PokerNum.方块Q.value()
                || p.value() == PokerNum.方块K.value()) {
            ret = 10;
        } else if (p.value() == PokerNum.方块A.value()) {
            ret = 1;
        } else if (p.value() == PokerNum.方块2.value()) {
            ret = 2;
        }
        return ret;
    }

    private void setBull(PokerGroup pokerGroup, int count) {
        switch (count % 10) {
            case 0:
                pokerGroup.setType(BullType.牛牛);
                break;
            case 1:
                pokerGroup.setType(BullType.牛1);
                break;
            case 2:
                pokerGroup.setType(BullType.牛2);
                break;
            case 3:
                pokerGroup.setType(BullType.牛3);
                break;
            case 4:
                pokerGroup.setType(BullType.牛4);
                break;
            case 5:
                pokerGroup.setType(BullType.牛5);
                break;
            case 6:
                pokerGroup.setType(BullType.牛6);
                break;
            case 7:
                pokerGroup.setType(BullType.牛7);
                break;
            case 8:
                pokerGroup.setType(BullType.牛8);
                break;
            case 9:
                pokerGroup.setType(BullType.牛9);
                break;
        }
    }
}
